package cn.flying.base.core.web.method;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;

import org.apache.commons.beanutils.BeanUtils;
import org.springframework.core.MethodParameter;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import cn.flying.base.common.vo.PageRequest;

/**
 * @description: 自定义参数解析 目的是处理PageRequest对象的泛型映射问题
 * @author: lvyong
 * @date: 2023年06月01日 16:46
 * @version: 1.0
 */
public class CustomHandlerMethodArgumentResolver implements HandlerMethodArgumentResolver {

    /**
     * Whether the given {@linkplain MethodParameter method parameter} is
     * supported by this resolver.
     *
     * @param parameter the method parameter to check
     * @return {@code true} if this resolver supports the supplied parameter;
     * {@code false} otherwise
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> parameterType = parameter.getParameterType();
        //只处理PageRequest分页查询参数对象
        if (PageRequest.class.getName().equals(parameterType.getName())) {
            return true;
        }
        return false;
    }

    /**
     * Resolves a method parameter into an argument value from a given request.
     * A {@link ModelAndViewContainer} provides access to the model for the
     * request. A {@link WebDataBinderFactory} provides a way to create
     * a {@link WebDataBinder} instance when needed for data binding and
     * type conversion purposes.
     *
     * @param parameter     the method parameter to resolve. This parameter must
     *                      have previously been passed to {@link #supportsParameter} which must
     *                      have returned {@code true}.
     * @param mavContainer  the ModelAndViewContainer for the current request
     * @param webRequest    the current request
     * @param binderFactory a factory for creating {@link WebDataBinder} instances
     * @return the resolved argument value, or {@code null} if not resolvable
     * @throws Exception in case of errors with the preparation of argument values
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        PageRequest pageRequest = new PageRequest();
        pageRequest.setPageNum(Integer.valueOf(webRequest.getParameter("pageNum")));
        pageRequest.setPageSize(Integer.valueOf(webRequest.getParameter("pageSize")));

        //获取方法的参数的泛型类型
        Type genericParameterType = parameter.getGenericParameterType();
        if (genericParameterType instanceof ParameterizedType) {
            ParameterizedType parameterType1 = (ParameterizedType) genericParameterType;
            Type[] actualTypeArguments = parameterType1.getActualTypeArguments();
            Type actualTypeArgument = actualTypeArguments[0];
            Class aClass = (Class) actualTypeArgument;
            //泛型对象
            Object instance = aClass.newInstance();

            Field[] declaredFields = aClass.getDeclaredFields();

            for (Field field : declaredFields) {
                if (StringUtils.hasText(webRequest.getParameter(field.getName()))) {
                    if (Date.class.getName().equals(field.getType().getName())) {

                    } else {

                    }
                    BeanUtils.setProperty(instance, field.getName(), webRequest.getParameter(field.getName()));
                }
            }

            pageRequest.setParam(instance);
        }

        return pageRequest;
    }
}
